/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-11-06     SummerGift   first version
 * 2020-7-10      baiyang      modified SystemClock_Config
 */

#include "board.h"
#ifdef BSP_USING_SPI
#include "drv_spi.h"

#ifdef RT_USING_SPI_MSD
#include "spi_msd.h"
#endif

#endif

#if defined(RT_USING_FAL)
#include <fal.h>
#endif

#define LED_R1_Pin GPIO_PIN_1
#define LED_R1_GPIO_Port GPIOC
#define LED_G1_Pin GPIO_PIN_2
#define LED_G1_GPIO_Port GPIOC
#define LED_B1_Pin GPIO_PIN_3
#define LED_B1_GPIO_Port GPIOC
#define BATT_VOLTAGE_SENS_Pin GPIO_PIN_2
#define BATT_VOLTAGE_SENS_GPIO_Port GPIOA
#define BATT_CURRENT_SENS_Pin GPIO_PIN_3
#define BATT_CURRENT_SENS_GPIO_Port GPIOA
#define SH_CS_Pin GPIO_PIN_4
#define SH_CS_GPIO_Port GPIOA
#define RCININT_Pin GPIO_PIN_0
#define RCININT_GPIO_Port GPIOB
#define QM8_CS_Pin GPIO_PIN_1
#define QM8_CS_GPIO_Port GPIOB
#define PWM1_Pin GPIO_PIN_9
#define PWM1_GPIO_Port GPIOE
#define SPL06_CS_Pin GPIO_PIN_10
#define SPL06_CS_GPIO_Port GPIOE
#define PWM2_Pin GPIO_PIN_11
#define PWM2_GPIO_Port GPIOE
#define BMI2_CS_Pin GPIO_PIN_12
#define BMI2_CS_GPIO_Port GPIOE
#define PWM3_Pin GPIO_PIN_13
#define PWM3_GPIO_Port GPIOE
#define PWM4_Pin GPIO_PIN_14
#define PWM4_GPIO_Port GPIOE
#define QMI_CS_Pin GPIO_PIN_15
#define QMI_CS_GPIO_Port GPIOE
#define I2C2_SCL_Pin GPIO_PIN_10
#define I2C2_SCL_GPIO_Port GPIOB
#define I2C2_SDA_Pin GPIO_PIN_11
#define I2C2_SDA_GPIO_Port GPIOB
#define PWM5_Pin GPIO_PIN_12
#define PWM5_GPIO_Port GPIOD
#define PWM6_Pin GPIO_PIN_13
#define PWM6_GPIO_Port GPIOD
#define PWM7_Pin GPIO_PIN_14
#define PWM7_GPIO_Port GPIOD
#define PWM8_Pin GPIO_PIN_15
#define PWM8_GPIO_Port GPIOD
#define FLASH_CS_Pin GPIO_PIN_8
#define FLASH_CS_GPIO_Port GPIOC
#define SDCARD_CS_Pin GPIO_PIN_9
#define SDCARD_CS_GPIO_Port GPIOC
#define I2C1_SCL_Pin GPIO_PIN_8
#define I2C1_SCL_GPIO_Port GPIOB
#define I2C1_SDA_Pin GPIO_PIN_9
#define I2C1_SDA_GPIO_Port GPIOB

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
    // 复位RCC
    // bootloader会先配置RCC，导致后配置时失败
    HAL_RCC_DeInit();

    // 防止bootloader更改BASEPRI的值，造成rtthread调度器无法正常工作
    // BASEPRI 设置为n后，屏蔽所有优先级数值大于等于n的中断和异常
    __set_BASEPRI(0);

    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    /** Configure the main internal regulator output voltage
    */
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /** Initializes the RCC Oscillators according to the specified parameters
    * in the RCC_OscInitTypeDef structure.
    */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 12;
    RCC_OscInitStruct.PLL.PLLN = 168;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    RCC_OscInitStruct.PLL.PLLQ = 7;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    /** Initializes the CPU, AHB and APB buses clocks
    */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
    {
        Error_Handler();
    }
}

#ifdef BSP_USING_SPI
int stm32_hw_spi_init(void)
{
    /* rt name max is 8 (RT_NAME_MAX   8) */
    rt_hw_spi_device_attach("spi1", "spi1_d1", QMI_CS_GPIO_Port, QMI_CS_Pin);

    /* rt name max is 8 (RT_NAME_MAX   8) */
    rt_hw_spi_device_attach("spi1", "spi1_d2", QM8_CS_GPIO_Port, QM8_CS_Pin);

    /* rt name max is 8 (RT_NAME_MAX   8) */
    rt_hw_spi_device_attach("spi1", "spi1_d3", SH_CS_GPIO_Port, SH_CS_Pin);

    /* rt name max is 8 (RT_NAME_MAX   8) */
    rt_hw_spi_device_attach("spi1", "spi1_d4", BMI2_CS_GPIO_Port, BMI2_CS_Pin);

    /* rt name max is 8 (RT_NAME_MAX   8) */
    rt_hw_spi_device_attach("spi1", "spi1_d5", SPL06_CS_GPIO_Port, SPL06_CS_Pin);

    /* rt name max is 8 (RT_NAME_MAX   8) */
    rt_hw_spi_device_attach("spi3", "spi3_d1", FLASH_CS_GPIO_Port, FLASH_CS_Pin);

    /* rt name max is 8 (RT_NAME_MAX   8) */
    rt_hw_spi_device_attach("spi3", "spi3_d2", SDCARD_CS_GPIO_Port, SDCARD_CS_Pin);

    return 1;
}
INIT_DEVICE_EXPORT(stm32_hw_spi_init);


#ifdef RT_USING_SPI_MSD
static int apgdstv2_mnt_init(void)
{
    // sd spi总线速度400k
    // spi总线速度太快，在spi DMA下会有问题
    // 如，在控制台使用ls命令，无法读取sd卡里的内容
    msd_init("sd0", "spi3_d2");

    return 0;
}
INIT_COMPONENT_EXPORT(apgdstv2_mnt_init);

#endif

#endif

#if defined(RT_USING_FAL)
static int apgdstv2_fal_init(void)
{
    return fal_init();
}
INIT_COMPONENT_EXPORT(apgdstv2_fal_init);
#endif

#define RT_APP_PART_ADDR 0x08010000
/**
Function ota_app_vtor_reconfig
Description Set Vector Table base location to the start addr of app(RT_APP_PART_ADDR).
*/
static int ota_app_vtor_reconfig(void)
{
    #define NVIC_VTOR_MASK 0x3FFFFF80
    /* Set the Vector Table base location by user application firmware definition */
    SCB->VTOR = RT_APP_PART_ADDR & NVIC_VTOR_MASK;

    return 0;
}
INIT_BOARD_EXPORT(ota_app_vtor_reconfig);

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static int MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, LED_R1_Pin|LED_G1_Pin|LED_B1_Pin|FLASH_CS_Pin
                          |SDCARD_CS_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(SH_CS_GPIO_Port, SH_CS_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(QM8_CS_GPIO_Port, QM8_CS_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOE, SPL06_CS_Pin|BMI2_CS_Pin|QMI_CS_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, I2C2_SCL_Pin|I2C2_SDA_Pin|I2C1_SCL_Pin|I2C1_SDA_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pins : LED_R1_Pin LED_G1_Pin LED_B1_Pin */
  GPIO_InitStruct.Pin = LED_R1_Pin|LED_G1_Pin|LED_B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : SH_CS_Pin */
  GPIO_InitStruct.Pin = SH_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(SH_CS_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : QM8_CS_Pin */
  GPIO_InitStruct.Pin = QM8_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(QM8_CS_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : SPL06_CS_Pin BMI2_CS_Pin QMI_CS_Pin */
  GPIO_InitStruct.Pin = SPL06_CS_Pin|BMI2_CS_Pin|QMI_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /*Configure GPIO pins : I2C2_SCL_Pin I2C2_SDA_Pin I2C1_SCL_Pin I2C1_SDA_Pin */
  GPIO_InitStruct.Pin = I2C2_SCL_Pin|I2C2_SDA_Pin|I2C1_SCL_Pin|I2C1_SDA_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pins : FLASH_CS_Pin SDCARD_CS_Pin */
  GPIO_InitStruct.Pin = FLASH_CS_Pin|SDCARD_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  return 0;
}
INIT_BOARD_EXPORT(MX_GPIO_Init);
